package com.ruiysoft.service.statement.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.itopener.lock.redisson.spring.boot.autoconfigure.LockAction;
import com.itopener.lock.redisson.spring.boot.autoconfigure.LockType;
import com.rabbitmq.client.Channel;
import com.ruiysoft.conf.mq.OrderMqConfig;
import com.ruiysoft.controller.sys.api.InnerMicroprogramApi;
import com.ruiysoft.controller.sys.dto.CalculationDto;
import com.ruiysoft.controller.sys.res.CalculationResponse;
import com.ruiysoft.entity.order.OrderMain;
import com.ruiysoft.entity.statement.StatementShop;
import com.ruiysoft.entity.statement.StatementUser;
import com.ruiysoft.pub.core.Result;
import com.ruiysoft.service.order.facade.OrderPubFacade;
import com.ruiysoft.service.order.mq.bean.OrderMQAfterOperateBean;
import com.ruiysoft.service.statement.IStatementShopService;
import com.ruiysoft.service.statement.IStatementUserService;
import com.ruiysoft.service.statement.consts.StatementType;
import com.ruiysoft.service.sys.ISysMicroShopService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.support.AmqpHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Component
public class StatementSubscribe {


	private static final Logger log = LoggerFactory.getLogger(StatementSubscribe.class);
	@Resource
	private IStatementShopService statementShopService;
	@Resource
	private IStatementUserService statementUserService;
	@Resource
	OrderPubFacade orderPubFacade;
	@Resource
	ISysMicroShopService shopService;
	@Resource
	private InnerMicroprogramApi innerMicroprogramApi;
	@RabbitListener(
			bindings = @QueueBinding(
					value = @Queue(value = OrderMqConfig.ORDER_AFTER_OPERATE_QUEUE_NAME, durable = "true", autoDelete="false"),
					exchange = @Exchange(value = OrderMqConfig.ORDER_AFTER_OPERATE_EXCHANGE_NAME),
					key = OrderMqConfig.ORDER_AFTER_OPERATE_ROUTE_KEY)
	)
	@Transactional
	public void onMessage(Message message, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, Channel channel) throws IOException {
		log.info("获取订单消息--{}",message);
		String json = new String(message.getBody(), StandardCharsets.UTF_8);
		channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
		if(StringUtils.isNotBlank(json)){
			OrderMQAfterOperateBean orderMQAfterOperateBean = JSONObject.parseObject(json,OrderMQAfterOperateBean.class);
			switch (orderMQAfterOperateBean.getOperateType()){
				case CUSTOMER_PAID:
					//支付
					payHandle(orderMQAfterOperateBean);
					break;
				case SYSTEM_SIGN:
					//签收
					signHandle(orderMQAfterOperateBean);
					break;
				case SHOP_REFUND:
					//退款
					refundHandle(orderMQAfterOperateBean);
					break;
				case RETURNED_PURCHASE:
					//申请退款 冻结
					purcRefundHandle(orderMQAfterOperateBean);
					break;
			}
		}
		channel.basicAck(deliveryTag, false);
	}

	@LockAction(value = "#bean.orderNo", lockType = LockType.REENTRANT_LOCK, waitTime = 30000)
	private void signHandle(OrderMQAfterOperateBean bean) {
		statementShopService.update(new StatementShop().setArrivalDate(bean.getCashWithdrawableTime()),new UpdateWrapper<StatementShop>().eq("trade_no",bean.getOrderNo()));
		statementUserService.update(new StatementUser().setArrivalDate(bean.getCashWithdrawableTime()),new UpdateWrapper<StatementUser>().eq("trade_no",bean.getOrderNo()));
	}

	@LockAction(value = "#bean.orderNo", lockType = LockType.REENTRANT_LOCK, waitTime = 30000)
	private void payHandle(OrderMQAfterOperateBean bean) {
		//先查询是否处理过此单号
		int cout = statementShopService.count(new QueryWrapper<StatementShop>().eq("trade_no",bean.getOrderNo()).eq("type",StatementType.income.getIndex()));
		Result<List<CalculationResponse>> result = innerMicroprogramApi.calculation(new CalculationDto().setShopId(bean.getShopId())
				.setOrderTime(bean.getPaidTime()).setPersonnelId(bean.getUserId()).setAmount(new BigDecimal(bean.getPayAmount().toString())));
		AtomicReference<Long> shareMoney = new AtomicReference<>(0L);
		//log.info("获取分润人员返回++++++++++++++++++++--{}",JSONObject.toJSONString(result));
		if(result!=null&&result.isSuccess()){
			//log.info("开始执行魏雪刚的返佣比例计算");
//			OrderMain om = orderPubFacade.getOrderMain(bean.getOrderNo());
//			shopService.calculationWxg(om);
			/*
			List<StatementUser> statementUsers = result.getData().stream()
					.peek(resource-> shareMoney.updateAndGet(v -> v + resource.getAmount().longValue()))
					.map(resource->new StatementUser()
							.setUserId(resource.getPersonnelId())
							.setShopId(resource.getShopId())
							.setMoney(resource.getAmount().longValue())
							.setFreeze(false)
//							.setArrivalDate(bean.getCashWithdrawableTime())
							.setTradeDate(bean.getPaidTime())
							.setTradeNo(bean.getOrderNo())
							.setType(StatementType.income.getIndex())
							.setSummary("订单分润，单号"+bean.getOrderNo())
					).collect(Collectors.toList());
			if(!statementUsers.isEmpty()){
                statementUserService.saveBatch(statementUsers);
            }*/
		}

		// 支付成功后插入新的交易记录
		StatementShop statementShop = new StatementShop()
				.setShopId(bean.getShopId())
				.setFreeze(false)
				.setArrivalDate(bean.getCashWithdrawableTime())
				.setTradeDate(bean.getPaidTime())
				.setTradeNo(bean.getOrderNo())
				.setType(StatementType.income.getIndex())
				.setSummary("销售收入，单号"+bean.getOrderNo())
				.setShareMoney(shareMoney.get())
				.setMoney(bean.getPayAmount());

		statementShopService.save(statementShop);
		log.info("这应该是入账的地方，成功了就能提现了！！！");
	}

	@LockAction(value = "#bean.orderNo", lockType = LockType.REENTRANT_LOCK, waitTime = 30000)
	private void purcRefundHandle(OrderMQAfterOperateBean bean) {
		statementShopService.update(new StatementShop().setFreeze(true),new UpdateWrapper<StatementShop>().eq("trade_no",bean.getOrderNo()));
		statementUserService.update(new StatementUser().setFreeze(true),new UpdateWrapper<StatementUser>().eq("trade_no",bean.getOrderNo()));
	}
	@LockAction(value = "#bean.orderNo", lockType = LockType.REENTRANT_LOCK, waitTime = 30000)
	private void refundHandle(OrderMQAfterOperateBean bean) {
		//TODO 没有自动退款
		//先查询是否处理过此单号
		int cout = statementShopService.count(new QueryWrapper<StatementShop>().eq("trade_no",bean.getOrderNo()).eq("type",StatementType.expenditure.getIndex()));
		Result<List<CalculationResponse>> result = innerMicroprogramApi.calculation(new CalculationDto().setShopId(bean.getShopId())
				.setOrderTime(bean.getPaidTime()).setPersonnelId(bean.getUserId()).setAmount(new BigDecimal(bean.getPayAmount().toString())));
		if(result!=null&&result.isSuccess()){
			List<StatementUser> statementUsers = result.getData().stream()
					.map(resource->new StatementUser()
							.setUserId(resource.getPersonnelId())
							.setShopId(resource.getShopId())
							.setMoney(resource.getAmount().longValue())
							.setFreeze(false)
							.setArrivalDate(bean.getCashWithdrawableTime())
							.setTradeDate(bean.getPaidTime())
							.setTradeNo(bean.getOrderNo())
							.setType(StatementType.expenditure.getIndex())
							.setSummary("买家退货，单号"+bean.getOrderNo())
					).collect(Collectors.toList());
            if(!statementUsers.isEmpty()){
                statementUserService.saveBatch(statementUsers);
            }
		}
		StatementShop statementShop = new StatementShop()
				.setShopId(bean.getShopId())
				.setFreeze(false)
				.setArrivalDate(bean.getCashWithdrawableTime())
				.setTradeDate(bean.getPaidTime())
				.setTradeNo(bean.getOrderNo())
				.setType(StatementType.expenditure.getIndex())
				.setSummary("买家退货，单号"+bean.getOrderNo())
				.setMoney(bean.getPayAmount());
		statementShopService.save(statementShop);
		//更新收入为正常
		statementShopService.update(new StatementShop().setFreeze(false).setArrivalDate(new Date()),new UpdateWrapper<StatementShop>().eq("trade_no",bean.getOrderNo()).eq("type",StatementType.income.getIndex()));
		statementUserService.update(new StatementUser().setFreeze(false).setArrivalDate(new Date()),new UpdateWrapper<StatementUser>().eq("trade_no",bean.getOrderNo()).eq("type",StatementType.income.getIndex()));
	}
}
